﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

/// <summary>
/// 更新面板
/// </summary>
public class UpdateView : ViewBase
{
    /// <summary>
    /// 总下载进度
    /// </summary>
    public Slider allFileslider;
    /// <summary>
    /// 当前文件下载进度
    /// </summary>
    public Slider nowFileslider;

    public Text t1;
    public Text t2;
    public Text t3;
    public Text t4;

    /// <summary>
    /// 资源服务器地址
    /// </summary>
    string serverRoot = "http://www.ganghood.net.cn/Game/";
    /// <summary>
    /// 服务器端版本文件地址
    /// </summary>
    string serverVerUrl;
    /// <summary>
    /// assetbundle文件的更新地址
    /// </summary>
    string abRoot;
    /// <summary>
    /// 本地ab文件存放路径
    /// </summary>
    static string abPath;

    /// <summary>
    /// 更新文件的队列
    /// </summary>
    Queue<Content> upContent = new Queue<Content>();

    /// <summary>
    /// 已经下载好的数量
    /// </summary>
    private int readyCount = 0;
    /// <summary>
    /// 总数量
    /// </summary>
    private int allCount = 0;
    /// <summary>
    /// 总进度
    /// </summary>
    private float allProgress;
    /// <summary>
    /// 当前文件的下载进度
    /// </summary>
    private float nowProgress;

    // Use this for initialization
    void Start()
    {
        abPath = PathMgr.Instance.abPersistentDataPathRoot;

        serverVerUrl = serverRoot + Util.GetPlatformName(Application.platform) + "/VersionMD5.txt";
        abRoot = serverRoot + Util.GetPlatformName(Application.platform) + "/";

        StartCoroutine(DownLoadVersion());
    }

    public override void Init(params object[] args)
    {
        base.Init(args);
        layer = PanelLayer.Panel;
    }

    public override void OnShowing()
    {
        base.OnShowed();
        allFileslider = panelObj.transform.Find("Slider1").GetComponent<Slider>();
        nowFileslider = panelObj.transform.Find("Slider2").GetComponent<Slider>();

        t1 = panelObj.transform.Find("t1").GetComponent<Text>();
        t2 = panelObj.transform.Find("t2").GetComponent<Text>();
        t3 = panelObj.transform.Find("t3").GetComponent<Text>();
        t4 = panelObj.transform.Find("t4").GetComponent<Text>();
    }

    bool isStart = false;
    bool isRun = false;

    public override void Update()
    {
        if (isStart)
        {
            t1.text = "所有文件下载进度：" + allProgress;
            t2.text = "当前文件下载进度：" + nowProgress;
            t3.text = "已下载文件数：" + readyCount;
            t3.text = "未下载文件数：" + upContent.Count;

            allFileslider.value = allProgress;
            nowFileslider.value = nowProgress;
        }
        if (isStart && !isRun && upContent.Count > 0)
        {
            Log.Debug("未下载文件数：" + upContent.Count);
            isRun = true;
            Content content = upContent.Dequeue();
            StartCoroutine(DownFile(content));
        }
    }

    void StartDownLoad()
    {
        isStart = true;
    }

    /// <summary>
    /// 服务器端版本信息
    /// </summary>
    VerInfo serverVerInfo;

    /// <summary>
    /// 下载服务器端资源版本信息
    /// </summary>
    /// <returns></returns>
    IEnumerator DownLoadVersion()
    {
        WWW www = new WWW(serverVerUrl);
        Log.Debug("serverVerUrl:" + serverVerUrl);
        yield return www;
        Log.Debug("www.text:" + www.text);

        if (File.Exists(abPath + "VersionMD5-new.txt"))
        {
            File.Delete(abPath + "VersionMD5-new.txt");
        }
        FileStream fs = new FileStream(abPath + "VersionMD5-new.txt", FileMode.Create);
        //获得字节数组
        byte[] data = System.Text.Encoding.Default.GetBytes(www.text);
        //开始写入
        fs.Write(data, 0, data.Length);
        //清空缓冲区、关闭流
        fs.Flush();
        fs.Close();

        serverVerInfo = ReadMD5File(abPath + "VersionMD5-new.txt");
        Log.Debug(serverVerInfo.version.ToString());

        //本地有版本文件
        if (File.Exists(abPath + "VersionMD5.txt"))
        {
            VerInfo localVerInfo = ReadMD5File(abPath + "VersionMD5.txt");
            //服务器版本号高于本地版本号
            if (serverVerInfo.version >= localVerInfo.version)
            {
                VerInfo upInfo = GetUpInfo(serverVerInfo, localVerInfo);

                for (int i = 0; i < upInfo.content.Count; i++)
                {
                    Content content = new Content();
                    content.name = upInfo.content[i].name;
                    content.filePath = abPath + upInfo.content[i].name;
                    content.md5 = upInfo.content[i].md5;
                    content.url = abRoot + upInfo.content[i].name;
                    upContent.Enqueue(content);
                }
            }
        }
        //本地没有版本文件
        else
        {
            for (int i = 0; i < serverVerInfo.content.Count; i++)
            {
                Content content = new Content();
                content.name = serverVerInfo.content[i].name;
                content.filePath = abPath + serverVerInfo.content[i].name;
                content.md5 = serverVerInfo.content[i].md5;
                content.url = abRoot + serverVerInfo.content[i].name;
                upContent.Enqueue(content);
            }
        }

        if (upContent.Count > 0)
        {
            allCount = upContent.Count;
            StartDownLoad();
        }
        else
        {
            UpdateComplete();
        }
    }

    /// <summary>
    /// 下载文件
    /// </summary>
    /// <param name="content"></param>
    /// <returns></returns>
    IEnumerator DownFile(Content content)
    {
        Log.Debug("文件url：" + content.url);
        UnityWebRequest headRequest = UnityWebRequest.Head(content.url);
        yield return headRequest.SendWebRequest();
        //网络文件长度
        var totalLength = long.Parse(headRequest.GetResponseHeader("Content-Length"));
        Log.Debug("网络文件长度:" + totalLength);
        var fs = new FileStream(content.filePath, FileMode.OpenOrCreate, FileAccess.Write);
        //本地文件长度
        var localLength = fs.Length;
        Log.Debug("本地文件长度:" + localLength);
        if (localLength < totalLength)
        {
            fs.Seek(localLength, SeekOrigin.Begin);

            var request = UnityWebRequest.Get(content.url);
            request.SetRequestHeader("Range", "bytes=" + localLength + "-");

            yield return request.SendWebRequest();
            Log.Debug("返回信息：" + request.responseCode + ":" + request.error);

            if (string.IsNullOrEmpty(request.error) && (request.responseCode == 200 || request.responseCode == 206))
            {
                var index = 0;
                bool state = true;
                while (state)
                {
                    var buff = request.downloadHandler.data;
                    if (buff != null)
                    {
                        var length = buff.Length - index;
                        fs.Write(buff, index, length);
                        index += length;
                        localLength += length;

                        nowProgress = localLength / (float)totalLength;

                        Log.Debug("nowProgress:" + nowProgress);
                        if (localLength == totalLength)
                        {
                            fs.Close();
                            fs.Dispose();

                            nowProgress = 1f;

                            CheckeFile(content);
                            state = false;
                        }
                    }
                }
            }
            else
            {
                Log.Debug("下载出错：" + request.responseCode + ":" + request.error);
                fs.Close();
                fs.Dispose();
                isRun = false;
            }

        }
        else
        {
            fs.Close();
            fs.Dispose();

            nowProgress = 1f;

            CheckeFile(content);
        }
    }

    /// <summary>
    /// 检查文件完整性
    /// </summary>
    void CheckeFile(Content content)
    {
        if (File.Exists(content.filePath))
        {
            if (Util.GetFileMD5(abPath + content.name) == content.md5)
            {
                Log.Debug("已下载并通过校验：" + abPath + content.name);
                readyCount += 1;
                allProgress = (float)((float)readyCount / (float)allCount);

                if (upContent.Count < 1)
                {
                    Log.Debug("更新完成！");
                    //本地有版本文件
                    if (File.Exists(abPath + "VersionMD5.txt"))
                    {
                        File.Delete(abPath + "VersionMD5.txt");
                    }

                    File.Copy(abPath + "VersionMD5-new.txt", abPath + "VersionMD5.txt");
                    File.Delete(abPath + "VersionMD5-new.txt");

                    UpdateComplete();
                }
            }
            else
            {
                File.Delete(abPath + content.name);
                Log.Debug("校验失败删除重新加入下载队列：" + abPath + content.name);
                upContent.Enqueue(content);
            }
        }
        else
        {
            Log.Debug("校验失败删除重新加入下载队列：" + abPath + content.name);
            upContent.Enqueue(content);
        }

        isRun = false;
    }

    /// <summary>
    /// 完成更新
    /// </summary>
    void UpdateComplete()
    {
        isStart = false;
        UIMgr.Instance.Show<LoginView>();
        Close();
    }

    /// <summary>
    /// 比较版本信息
    /// </summary>
    /// <param name="serVer"></param>
    /// <param name="localVer"></param>
    /// <returns></returns>
    public VerInfo GetUpInfo(VerInfo serVer, VerInfo localVer)
    {
        VerInfo upInfo = new VerInfo();
        upInfo.content = new List<Content>();
        foreach (Content content in serVer.content)
        {
            if (!localVer.content.Contains(content) || !File.Exists(abPath + content.name))
            {
                Log.Debug("本地缺少文件：" + abRoot + content.name);
                upInfo.content.Add(content);
            }
        }

        return upInfo;
    }

    public static VerInfo ReadMD5File(string fileName)
    {
        VerInfo versionInfo = new VerInfo();
        versionInfo.content = new List<Content>();
        versionInfo.version = 0;
        // 如果文件不存在，则直接返回
        if (File.Exists(fileName) == false)
        {
            return versionInfo;
        }

        try
        {
            XmlDocument XmlDoc = new XmlDocument();
            XmlDoc.Load(fileName);
            XmlElement XmlRoot = XmlDoc.DocumentElement;

            foreach (XmlNode node in XmlRoot.ChildNodes)
            {
                //Log.Debug("node.Name:" + node.Name);
                if (node.Name == "File")
                {
                    if ((node is XmlElement) == false)
                    {
                        continue;
                    }
                    Content ui = new Content();
                    ui.name = (node as XmlElement).GetAttribute("name");
                    ui.md5 = (node as XmlElement).GetAttribute("md5");
                    versionInfo.content.Add(ui);
                }
                else
                {
                    versionInfo.version = Convert.ToInt32((node as XmlElement).GetAttribute("code"));
                }
            }

            XmlRoot = null;
            XmlDoc = null;
        }
        catch (Exception e)
        {
            Debug.LogError(e.ToString());
        }
        return versionInfo;
    }

    /// <summary>
    /// 更新的版本信息
    /// </summary>
    public struct VerInfo
    {
        public int version;
        public List<Content> content;
    }

    /// <summary>
    /// 更新内容信息
    /// </summary>
    public struct Content
    {
        /// <summary>
        /// 文件的url下载地址
        /// </summary>
        public string url;

        /// <summary>
        /// 文件名
        /// </summary>
        public string name;

        /// <summary>
        /// 文件的保存路径
        /// </summary>
        public string filePath;

        /// <summary>
        /// 文件的md5
        /// </summary>
        public string md5;
    }

    /// <summary>
    /// 下载输出信息
    /// </summary>
    public struct OutInfo
    {
        /// <summary>
        /// 总长度
        /// </summary>
        public long TotalBytesToReceive;
        /// <summary>
        /// 已接收的字节数
        /// </summary>
        public long BytesReceived;
    }
}

public class DownloaderHandler : DownloadHandlerScript
{
    public float progress;
    private int ContentLength = 0;
    private int DownedLength = 0;

    FileStream fs;

    public DownloaderHandler(string FilePath) : base(new byte[1024])
    {
        fs = new FileStream(FilePath, FileMode.OpenOrCreate);
    }

    protected override bool ReceiveData(byte[] data, int dataLength)
    {
        if (data == null || data.Length < 1)
        {
            return false;
        }
        fs.Write(data, 0, dataLength);
        DownedLength += dataLength;

        progress = DownedLength / ContentLength;
        Log.Debug("当前文件进度：" + progress);
        return true;
    }

    protected override void CompleteContent()
    {
        fs.Close();
        fs.Dispose();
    }

    protected override void ReceiveContentLength(int contentLength)
    {
        ContentLength = contentLength;
    }
}